
package artistic;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

/**
 * Class for windows that the user
 * can paint in, i.e. use paint tools
 * in.
 * 
 * @author Mikael Andersson
 * @author Rurik Högfeldt
 */

public class PaintWindow extends JPanel
            implements MouseListener,
            MouseMotionListener,
            MouseWheelListener
{
    private class PaintCanvas extends JPanel
    {
        private PaintWindow parent;

        public PaintCanvas(PaintWindow w)
        {
            parent = w;
            addMouseListener(w);
            addMouseMotionListener(w);
            addMouseWheelListener(w);
        }

        @Override
        public void update(Graphics g)
        {
            paint(g);
        }

        @Override
        public void paint(Graphics g)
        {
            PaintImage image = parent.getImage();

            image.draw(g);
        }

    }

    public PaintWindow()
    {
        setLayout(new FlowLayout(FlowLayout.LEFT, 2, 1));
        this.validate();
        this.setVisible( true );
    }

    public PaintWindow(ToolBox toolBox)
    {
        this(toolBox, new PaintImage(640, 480));
    }

    private PaintCanvas canvas;
    private ToolBox toolBox;

    public PaintWindow(ToolBox toolBox, PaintImage image)
    {

        setLayout(new FlowLayout(FlowLayout.LEFT, 2, 1));
        //setBackground(Color.WHITE);

        this.toolBox = toolBox;
        this.image = image;

        canvas = new PaintCanvas(this);
        this.add(canvas);
        canvas.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
        
        this.validate();
        this.setVisible( true );
        
        canvas.repaint();
    }

    /**
     * The image used by the window.
     */
    private PaintImage image;

    /**
     * Get image associated with paint window.
     * 
     * @return The window's image.
     */
    public PaintImage getImage()
    {
        return image;
    }

    public void newImage(int width, int height)
    {
        image = new PaintImage(width, height);
        
        this.canvas.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
        this.repaint();
    }

    public void loadImage(Image source)
    {
        int width = source.getWidth(null);
        int height = source.getHeight(null);
        image = new PaintImage(width, height);
        assert(image.getLayerCount() == 1);
        TiledCanvas canvas = image.getLayer(0);
        
        BufferedImage buffer =
                new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = buffer.createGraphics();
        g.drawImage(source, 0, 0, null);
        
        for(int y = 0; y<height; ++y)
        {
            for(int x = 0; x<width; ++x)
            {
                int color = buffer.getRGB(x,y);
                canvas.setPixel(x, y, color);
            }
        }

        this.canvas.setPreferredSize(new Dimension(image.getWidth(), image.getHeight()));
        this.repaint();
    }

    public void saveImage(File selectedFile) throws IOException{
        TiledCanvas canvas2 = image.getCombinedCanvas();
        int height = canvas2.getHeight();
        int width = canvas2.getWidth();

        BufferedImage buffer =
                new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

        for(int y = 0; y<height; ++y)
        {
            for(int x = 0; x<width; ++x)
            {
                int color = canvas2.getPixel(x,y);
                buffer.setRGB(x, y, color);

            }
        }
        ImageIO.write(buffer, "png", selectedFile);
    }

    @Override
    public void repaint()
    {
        super.repaint();
        if(canvas != null)
            canvas.repaint();
    }

    public void mouseClicked(MouseEvent e) {
        toolBox.getActiveTool().mouseCallback(this, e);
    }

    public void mousePressed(MouseEvent e) {
        toolBox.getActiveTool().mouseCallback(this, e);
    }

    public void mouseReleased(MouseEvent e) {
        toolBox.getActiveTool().mouseCallback(this, e);
    }

    public void mouseEntered(MouseEvent e) {
        toolBox.getActiveTool().mouseCallback(this, e);
    }

    public void mouseExited(MouseEvent e) {
        toolBox.getActiveTool().mouseCallback(this, e);
    }

    public void mouseDragged(MouseEvent e) {
        toolBox.getActiveTool().mouseCallback(this, e);
    }

    public void mouseMoved(MouseEvent e) {
        toolBox.getActiveTool().mouseCallback(this, e);
    }

    public void mouseWheelMoved(MouseWheelEvent e) {
        toolBox.getActiveTool().mouseWheelCallback(this, e);
    }
}
